package cn.xiaoke.damowang.lucky_audience.service.domain;

import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.beans.BeanUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class BiliBiliLuckyReservoir<T> {

    private final static Random random = new Random();

    private List<PrizeInfo> prizeList;
    private List<T> list;
    private int count;

    public List<WinningUserInfo> getWinningUserInfoList() {
        final List<WinningUserInfo> winningUserInfoList = new ArrayList<>(list.size());
        for (int i = 0; i < list.size(); i++) {
            final T t = list.get(i);
            final PrizeInfo prizeInfo = prizeList.get(i);
            final WinningUserInfo winningUserInfo = new WinningUserInfo();
            BeanUtils.copyProperties(t,winningUserInfo);
            BeanUtils.copyProperties(prizeInfo,winningUserInfo);
            winningUserInfoList.add(winningUserInfo);
        }
        return winningUserInfoList;
    }

    public int getCount() {
        return count;
    }

    public BiliBiliLuckyReservoir(PrizeInfo... infos) {
        prizeList = Arrays.stream(infos).flatMap(info -> {
            final Integer num = info.getNum();
            return Stream.generate(()->info.setNum(null)).limit(num);
        }).collect(Collectors.toList());
        list = new ArrayList<>(prizeList.size());
    }

    public void add(T t) {
        if (count < prizeList.size()) {
            list.add(t);
            count++;
        } else {
            final int rand = random.nextInt(++count);
            if (rand < prizeList.size()) {
                list.set(rand, t);
            }
        }
    }
    @Data
    @Accessors(chain = true)
    public static class PrizeInfo{
        //奖品名称
        String name;
        //奖品数量
        Integer num;
        //可以保留
        Boolean canRetain;
        //可以折现
        Boolean canDiscounting;
        //折现比例
        Integer discountingRatio;

        public PrizeInfo(String name, Integer num, Boolean canRetain, Boolean canDiscounting, Integer discountingRatio) {
            this.name = name;
            this.num = num;
            this.canRetain = canRetain;
            this.canDiscounting = canDiscounting;
            this.discountingRatio = discountingRatio;
        }
    }
    @Data
    public static class WinningUserInfo{
        //奖品名称
        String name;
        //奖品数量
        Integer num;
        //可以保留
        Boolean canRetain;
        //可以折现
        Boolean canDiscounting;
        //折现比例
        Integer discountingRatio;

        private long mid;

        private String nickname;

        @Override
        public String toString() {
            return "中奖者: " + nickname + ",\t B站ID: " + mid + ", 奖品名称: " + name
                    + ", 能否保留: " + (canRetain ? "能" : "否")
                    + ", 能否折现: " + (canDiscounting ? "能" : "否")
                    + (canDiscounting ? ",折现比例: 百分之" + discountingRatio : "");
        }
    }
}
